import {GeoJSON, WFS} from 'ol/format'
import {Vector} from 'ol/source'
import {Control, LineLayer, PointLayer, Zoom} from "@antv/l7";
import {findTableData} from "@/api/leakage/pgedit";
import * as turf from '@turf/turf'

export const pointScodeMap = {
  '水厂': '/images/gis-svg/GIS-TL_shuichang.png',
  '排气井': '/images/gis-svg/GIS-TL_paiqijing.svg',
  '阀门井': '/images/gis-svg/GIS-TL_famenjing.svg',
  '水源井': '/images/gis-svg/GIS-TL_shuiyuanjing.svg',
  // '三通': '/images/gis-svg/GIS-TL_santong.svg',
  // '转折点': '/images/gis-svg/GIS-TL_zhuanzhedian.svg',
  // '四通': '/images/gis-svg/GIS-TL_sitong.svg',
  // '预留口': '/images/gis-svg/GIS-TL_yuliukou.svg',
  '检修井': '/images/gis-svg/GIS-TL_jianxiujing.svg',
  // '直线点': '/images/gis-svg/GIS-TL_zhixiandian.svg',
  // '排气': '/images/gis-svg/GIS-TL_paiqifa.svg',
  '排气阀': '/images/gis-svg/GIS-TL_paiqifa.svg',
  '水表井': '/images/gis-svg/GIS-TL_shuibiaojing.svg',
  // '变径': '/images/gis-svg/GIS-TL_bianjingdian.svg',
  // '变径点': '/images/gis-svg/GIS-TL_bianjingdian.svg',
  '消防井': '/images/gis-svg/GIS-TL_xiaofangjing.svg',
  '水塔': '/images/gis-svg/GIS-TL_shuita.svg',
  '盖堵': '/images/gis-svg/GIS-TL_gaidu.svg',
  '阀门': '/images/gis-svg/GIS-TL_famen.png',
  '消防栓': '/images/gis-svg/GIS-TL_xiaofangbiao.svg',
  // '出地': '/images/gis-svg/GIS-TL_chudidian.svg',
  // '出地点': '/images/gis-svg/GIS-TL_chudidian.svg',
}

/**
 * 从WFS服务加载要素
 * @param wfsUrl
 * @param layerName
 * @param callback
 */
export function loadFeaturesByWFS(wfsUrl, layerName, tableName, callback) {
  const param = {
    service: 'WFS',
    version: '1.1.0',
    request: 'GetFeature',
    typeName: layerName,
    outputFormat: 'application/json',
    // maxFeatures: 3200,
    // srsName: srsName
    srsName: 'EPSG:4326',
    sortby: 'id'
  };

  callSQLViewByWFS(wfsUrl, 'qtgis:func_get_table_data_count', `tbl:${tableName}`, data => {
    const count = data.features[0].properties.count
    const pageSize = 3000
    const pageNum = Math.floor((count % pageSize === 0) ? (count / pageSize) : (count / pageSize + 1))
    const requests = []
    param.maxFeatures = pageSize
    for (let i = 0; i < pageNum; i++) {
      param.startIndex = i * pageSize
      const url = wfsUrl + '?' + new URLSearchParams(param).toString();
      requests[i] = fetch(url).then((res) => res.json())
    }

    Promise.all(requests).then(data => {
      const totalData = {
        crs: {
          "type": "name",
          "properties": {
            "name": "urn:ogc:def:crs:EPSG::4326"
          }
        },
        features: [],
        type: "FeatureCollection",
      }
      totalData.features = data.map(item => item.features).flat()
      callback(totalData)
    })
  })
}

export function callSQLViewByWFS(wfsUrl, viewName, viewParams, callback) {
  const param = {
    service: 'WFS',
    version: '1.1.0',
    request: 'GetFeature',
    typeName: viewName,
    outputFormat: 'application/json',
    maxFeatures: 3200,
    // srsName: srsName
    srsName: 'EPSG:4326',
    viewparams: viewParams
  };

  const url = wfsUrl + '?' + new URLSearchParams(param).toString();

  fetch(url).then((res) => res.json()).then((data) => {
    callback(data)
  })
  // http://localhost:8080/geoserver/wuchuan/ows?&typeName=wuchuan%3Afunc_shortestpath&viewparams=x1:111.434148;y1:41.144882;x2:111.434116;y2:41.14439
}

/**
 * 添加地图场景要素图片
 * @param scene
 */
export function initSceneImage(scene) {
  scene.addImage('famen', '/images/gis-svg/GIS-TL_famen.png');
  scene.addImage('shuichang', '/images/gis-svg/GIS-TL_shuichang.png');
  scene.addImage('xiaofangshuan', '/images/gis-svg/GIS-TL_xiaoquxiaohuoshuan.svg');
  scene.addImage('lianjiedian', '/images/gis-svg/GIS-TL_linkpoint.png');
  scene.addImage('qidian', '/images/gis-svg/GIS-TL_qidian.png');
  scene.addImage('zhongdian', '/images/gis-svg/GIS-TL_zhongdian.png');
  scene.addImage('huozaidian', '/images/gis-svg/GIS-TL_huozaidian.png');
  scene.addImage('baoguan', '/images/gis-svg/GIS-TL_leak_point.png');

  Object.keys(pointScodeMap).forEach(key => {
    scene.addImage(key, pointScodeMap[key]);
  })
}

/**
 * 添加地图放大缩小控件
 * @param scene
 * @param position
 */
export function initSceneZoomControl(scene, position = 'topleft') {
  const zoom = new Zoom({
    zoomInTitle: '放大',
    zoomOutTitle: '缩小',
    position: position
  });

  scene.addControl(zoom);

  return zoom
}

/**
 * 添加地图图例控件
 * @param scene
 * @param position
 */
export function initSceneLegendControl(scene, position = 'bottomleft') {
  // 添加地图图例
  const legendControl = new Control({
    position: position
  });

  legendControl.onAdd = function () {
    const el = document.createElement("div");
    el.className = "legend-box";

    const keys = Object.keys(pointScodeMap)
    for (let i = 0; i < keys.length; i++) {
      const key = keys[i]
      el.innerHTML += `<div>
                          <img style="width: 20px;height: 20px;" src="${pointScodeMap[key]}" alt=""/>
                          <span style="margin-left: 5px;">${key}</span>
                       </div>`
    }

    return el;
  };

  scene.addControl(legendControl);

  return legendControl
}


export function getGisLayers(scene, layerGroup) {
  const queryParams = {
    tableName: 'sys_gis_layer',
    pageNum: 1,
    pageSize: 999999
  }
  const geomLayerData = {}
  findTableData(queryParams).then(res => {
    if (res.code === 200 && res.data && res.data.length) {
      // geomLayerData.pointParams = res.data.filter(item => item.layer_type === 1)[0]
      // geomLayerData.pointTableName = this.geomLayerData.pointParams.target_table
      geomLayerData.lineParams = res.data.filter(item => item.layer_type === 2)[0]
      geomLayerData.lineTableName = geomLayerData.lineParams.target_table

      geomLayerData.tenant = geomLayerData.lineParams.tenant_id
      // 添加管线图层
      loadFeaturesByWFS(geomLayerData.lineParams.service_url, geomLayerData.lineParams.layer_prefix + ':' + geomLayerData.lineParams.layer_name, geomLayerData.lineTableName, (data) => {
        const {polylineLayer, polylineLabelLayer} = initPolylineLayer(data, (e) => {
          // console.log(e.feature.properties)
        })

        setTimeout(() => {
          scene.addLayer(polylineLayer);
          scene.addLayer(polylineLabelLayer);

          if (layerGroup) {
            layerGroup.push(polylineLayer)
            layerGroup.push(polylineLabelLayer)
          }
        }, 250)
      })
    }
  })
}

/**
 * 初始化管线图层
 * @param scene
 * @param data
 * @param layerClickCallback
 * @param color
 * @param size
 * @returns {{polylineLayer: ILayer}}
 */
export function initPolylineLayer(data, layerClickCallback, color = '#FF0000', size = 2) {
  const lineSourceData = JSON.parse(JSON.stringify(data))

  const polylineLayer = new LineLayer({
    zIndex: 1000
  }).source(lineSourceData)
    .shape('line')
    .size(size)
    // .color(color);
    .color('D_S', (value) => {
      let color = '#bb3a44'
      try {
        const iValue = parseInt(value)
        if (iValue < 100) {
          color = '#7facd6'
        } else if (iValue >= 100 && iValue < 200) {
          color = '#87d704'
        } else if (iValue >= 200 && iValue < 400) {
          color = '#fcb268'
        } else if (iValue >= 400 && iValue < 600) {
          color = '#e6c8ff'
        } else if (iValue >= 600 && iValue < 800) {
          color = '#ec808d'
        }
      } catch (err) {

      } finally {

      }

      return color
    });

  polylineLayer.on('click', (e) => {
    if (layerClickCallback) {
      layerClickCallback(e)
    }
  })

  const polylineLabelLayer = initLineLabelLayer(data)

  const event = new CustomEvent('initPolylineLayer', {});
  document.dispatchEvent(event);

  return {polylineLayer, polylineLabelLayer}
  // return {lineFeatures, lineSourceData, polylineLayer}
}

/**
 * 初始化管线口径文本标记图层
 * @param data
 */
export function initLineLabelLayer(data) {
  /*
   * 弧度转换为角度
   */
  function radiansToDegrees(radians) {
    const degrees = radians % (2 * Math.PI);
    return degrees * 180 / Math.PI;
  }

  // 文本标记数据
  const pointData = {
    "type": "FeatureCollection",
    "crs": {
      "type": "name",
      "properties": {}
    },
    "features": []
  }

  data.features.forEach(f => {
    if (f.properties.D_S) {
      const center = turf.center(f);
      // 口径大小
      center.properties.caliber = `DN${f.properties.D_S}`

      // 线段的起点和终点
      const firstPoint = f.geometry.type === 'LINESTRING' ? f.geometry.coordinates[0] : f.geometry.coordinates[0][0]
      const lastPoint = f.geometry.type === 'LINESTRING' ? f.geometry.coordinates[f.geometry.coordinates.length - 1] : f.geometry.coordinates[0][f.geometry.coordinates[0].length - 1]
      const dx = lastPoint[0] - firstPoint[0];
      const dy = lastPoint[1] - firstPoint[1];

      // 计算两个坐标点（起点和终点）的旋转角度
      const rotation = radiansToDegrees(Math.atan2(dy, dx))
      center.properties.rotation = isNaN(rotation) ? 0 : rotation

      pointData.features.push(center)
    }
  })

  const labelLayer = new PointLayer({zIndex: 1000})
    .source(pointData)
    .shape('caliber', 'text')
    .size(10)
    // .color('#084081')
    .color('blue')
    .style({
      textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
      textOffset: [0, 15], // 文本相对锚点的偏移量 [水平, 垂直]
      spacing: 2, // 字符间距
      padding: [1, 1], // 文本包围盒 padding [水平，垂直]，影响碰撞检测结果，避免相邻文本靠的太近
      stroke: '#ffffff', // 描边颜色
      strokeWidth: 2, // 描边宽度
      strokeOpacity: 1.0,
      // rotation: 60, // 常量旋转
      rotation: {
        // 字段映射旋转角度
        field: 'rotation',
        // value: [30, 270],
      },
    });

  const event = new CustomEvent('initPolylineLabelLayer', {});
  document.dispatchEvent(event);

  return labelLayer
}

/**
 * 初始化管点图层
 * @param scene
 * @param data
 * @param layerClickCallback
 * @param color
 * @param size
 */
export function initPointLayer(data, layerClickCallback) {
  // const pointFeatures = new GeoJSON().readFeatures(data)
  // const pointSourceData = JSON.parse(JSON.stringify(data))

  const pointLayerList = []

  const dataScodeMap = data.features.groupBy(item => item.properties.SCODE)

  // 常用图层
  Object.keys(pointScodeMap).forEach(scode => {
    // if (dataScodeMap[scode]) {
    const pointData = {features: dataScodeMap[scode], type: 'FeatureCollection'}

    const pointLayer = new PointLayer({zIndex: 1002})
      .source(pointData)
      .shape(scode)
      .size('SCODE', scodeValue => {
        return scodeValue === scode ? 8 : 2
      })
      .select({
        color: '#0c72dc',
        mix: 0.65,
      });

    pointLayer.on('click', (e) => {
      if (layerClickCallback) {
        layerClickCallback(e)
      }
    })

    let icon = pointScodeMap[scode]
    const layerItem = {
      name: scode,
      icon: icon.substring(icon.lastIndexOf('/') + 1),
      target: pointLayer,
      checked: true,
      count: pointData.features ? pointData.features.length : 0
    }
    pointLayerList.push(layerItem)
    // }
  });

  // 其他类型归结为其他图层 ----- begin
  const otherData = data.features.filter(item => !pointScodeMap[item.properties.SCODE])
  const otherPointLayer = new PointLayer({zIndex: 1003})
    .source({features: otherData, type: 'FeatureCollection'})
    .shape('lianjiedian')
    .size(8)
    .select({
      color: '#0c72dc',
      mix: 0.65,
    });
  otherPointLayer.on('click', (e) => {
    if (layerClickCallback) {
      layerClickCallback(e)
    }
  })

  otherPointLayer.hide()

  pointLayerList.push({
    name: '其他',
    icon: 'GIS-TL_linkpoint.png',
    target: otherPointLayer,
    checked: false,
    count: otherData.length
  })
  // 其他类型归结为其他图层 ----- end

  const event = new CustomEvent('initPointLayer', {});
  document.dispatchEvent(event);

  return {pointLayerList}
  // return {pointFeatures, pointSourceData, pointLayerList}
}

/**
 * 初始化地图图层数据
 * @param layerTreeData
 * @param polylineLayer
 * @param polylineLabelLayer
 * @param pointLayerList
 * @param callback
 */
export function initMapLayerTree(layerTreeData, polylineLayer, polylineLabelLayer, pointLayerList, callback) {
  layerTreeData.push({
    name: '管线图层',
    icon: 'GIS-TL_guanxian.png',
    children: [
      {
        name: '供水管线',
        icon: '',
        target: polylineLayer,
        checked: true
      },
      {
        name: '管径标记',
        icon: '',
        target: polylineLabelLayer,
        checked: true
      }
    ]
  })

  layerTreeData.push({
    name: '管点图层',
    icon: 'GIS-TL_guandian.png',
    checked: false,
    children: pointLayerList
  })

  const selectedTreeNodeKeys = []
  setDefaultCheckNodes(layerTreeData, selectedTreeNodeKeys)
  callback(selectedTreeNodeKeys)
}

/**
 * 设置图层树默认选中项
 * @param data
 * @param selectedTreeNodeKeys
 */
function setDefaultCheckNodes(data, selectedTreeNodeKeys) {
  const that = this
  data.forEach(item => {
    if (item.checked) {
      selectedTreeNodeKeys.push(item.name)
    }

    if (item.children && item.children.length) {
      setDefaultCheckNodes(item.children, selectedTreeNodeKeys)
    }
  })
}

/**
 * 添加要素
 */
export function addFeatureByWFS(wfsUrl, srsName, namespace, workSpaceName, layerName, feature, callback) {
  const wfs = new WFS();
  // 生成XML格式的WFS请求信息
  const transactXml = wfs.writeTransaction(
    [feature], null, null,
    {
      srsName: srsName,
      featureNS: namespace,
      featurePrefix: workSpaceName,
      featureType: [layerName],
    }
  );
  // 将XML格式请求信息序列化为字符串格式
  const transactStr = (new XMLSerializer()).serializeToString(transactXml);
  // 使用Fetch将请求发送到后端
  fetch(wfsUrl, {
    method: 'POST',
    mode: 'no-cors',
    body: transactStr,
    headers: {
      'Content-Type': 'text/xml'
    }
  }).then(res => {
    callback(res)
  });
}

export function operateByWFS(wfsUrl, transactionXml, callback) {
  // 使用Fetch将请求发送到后端
  fetch(wfsUrl, {
    method: 'POST',
    mode: 'no-cors',
    body: transactionXml,
    headers: {
      'Content-Type': 'text/xml'
    }
  }).then(res => {
    callback(res)
  });
}

/**
 * 更新要素
 */
export function updateFeatureByWFS(wfsUrl, srsName, namespace, workSpaceName, layerName, feature, callback) {
  const wfs = new WFS();
  // 生成XML格式的WFS请求信息
  const transactXml = wfs.writeTransaction(
    null, [feature], null,
    {
      srsName: srsName,
      featureNS: namespace,
      featurePrefix: workSpaceName,
      featureType: layerName,
    }
  )
  // 将XML格式请求信息序列化为字符串格式
  const transactStr = (new XMLSerializer()).serializeToString(transactXml);
  // console.log(wfsUrl, srsName, namespace, workSpaceName, layerName, feature, callback, transactStr)
  // 使用Fetch将请求发送到后端
  fetch(wfsUrl, {
    method: 'POST',
    mode: 'no-cors',
    body: transactStr,
    headers: {
      'Content-Type': 'text/xml'
    }
  }).then(res => {
    callback(res)
  });
}

/**
 * 删除要素
 */
export function deleteFeatureByWFS(wfsUrl, srsName, namespace, workSpaceName, layerName, feature, callback) {
  const wfs = new WFS();
  // 生成XML格式的WFS请求信息
  const transactXml = wfs.writeTransaction(
    null, null, [feature],
    {
      srsName: srsName,
      featureNS: namespace,
      featurePrefix: workSpaceName,
      featureType: [layerName],
    }
  )
  // 将XML格式请求信息序列化为字符串格式
  const transactStr = (new XMLSerializer()).serializeToString(transactXml);
  // 使用Fetch将请求发送到后端
  fetch(wfsUrl, {
    method: 'POST',
    mode: 'no-cors',
    body: transactStr,
    headers: {
      'Content-Type': 'text/xml'
    }
  }).then(res => {
    callback(res)
  });
}
